﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using SecureCommander.GUI;
using SecureCommander.Core;
using System.Windows;
using Microsoft.Win32;
using Microsoft.VisualBasic.FileIO;
using Ionic.Zip;

namespace SecureCommander.Helper
{
    class FileHelper
    {
        public static IconListManager IconManager = new IconListManager(IconReader.IconSize.Small);

        public static MessageBoxResult ShowMessage(string message, MessageBoxImage messageType)
        {
            return MessageBox.Show(message, "Secure Commander", MessageBoxButton.OK, messageType);
        }

        public static void SelectNewItem(UCExplorer explorer, String fullName)
        {
            int index = 0;
            foreach (ListViewContent item in explorer.lvContent.Items)
            {
                if (item.Tag.FullName == fullName)
                {
                    explorer.lvContent.SelectedIndex = index;
                    break;
                }
                index++;
            }
        }

        public static string GetAtributeString(FileAttributes att)
        {
            StringBuilder result = new StringBuilder("----");
            if ((att & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                result[0] = 'r';
            if ((att & FileAttributes.Archive) == FileAttributes.Archive)
                result[1] = 'a';
            if ((att & FileAttributes.Hidden) == FileAttributes.Hidden)
                result[2] = 'h';
            if ((att & FileAttributes.System) == FileAttributes.System)
                result[3] = 's';
            return result.ToString();
        }

        public static void DisplayExplorer(UCExplorer explorere)
        {
            try
            {
                explorere.lvContent.Items.Clear();

                DirectoryInfo thisDirInfo = new DirectoryInfo(explorere.CurrentDirectory);
                if (explorere.CurrentDirectory != Directory.GetDirectoryRoot(explorere.CurrentDirectory))
                {
                    explorere.lvContent.Items.Add(new ListViewContent("...",
                                                            "",
                                                            thisDirInfo.LastWriteTime.ToString(),
                                                            "File Folder",
                                                            IconManager.GetFolderIcon(thisDirInfo.FullName),
                                                            GetAtributeString(thisDirInfo.Attributes),
                                                            thisDirInfo.Parent));
                }

                foreach (DirectoryInfo dir in thisDirInfo.GetDirectories())
                {
                    if ((dir.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
                    {
                        explorere.lvContent.Items.Add(new ListViewContent(dir.Name,
                                                                "",
                                                                dir.LastWriteTime.ToString(),
                                                                "File Folder",
                                                                IconManager.GetFolderIcon(dir.FullName),
                                                                GetAtributeString(dir.Attributes),
                                                                dir));
                    }
                }

                foreach (FileInfo file in thisDirInfo.GetFiles())
                {
                    if ((file.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
                    {
                        explorere.lvContent.Items.Add(new ListViewContent(file.Name,
                                                                file.Length.ToString(),
                                                                file.LastWriteTime.ToString(),
                                                                NativeMethods.getTypeName(file.FullName),
                                                                IconManager.GetFileImage(file.FullName),
                                                                GetAtributeString(file.Attributes),
                                                                file));
                    }
                }
                explorere.lvContent.Focus();
            }
            catch (Exception ex)
            {
                ShowMessage(ex.Message, MessageBoxImage.Error);
                if (explorere.CurrentDirectory != Directory.GetDirectoryRoot(explorere.CurrentDirectory))
                {
                    if (explorere.lvContent.Items.Count > 0)
                    {
                        ListViewContent parentContent = (ListViewContent)explorere.lvContent.Items[0];
                        explorere.CurrentDirectory = parentContent.Tag.FullName;
                        FileHelper.DisplayExplorer(explorere);
                    }

                }

            }
        }

        public static void OpenItem(UCExplorer explorere, ListViewContent content)
        {
            if (content == null)
            {
                return;
            }
            if (content.Tag is DirectoryInfo)
            {
                string newDir = content.Tag.FullName;
                if (Directory.Exists(newDir) == false)
                {
                    MessageBox.Show("The directory " + newDir + "does not exist", "Cryptography", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                explorere.CurrentDirectory = newDir;
                DisplayExplorer(explorere);
            }
            else
            {
                try
                {
                    System.Diagnostics.Process.Start(content.Tag.FullName);
                }
                catch
                {
                    MessageBox.Show("Can not open this file", "Cryptography", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        public static void NewFolder(UCExplorer explorer)
        {
            FormNewFolder frm = new FormNewFolder();

            if (frm.ShowDialog().Value)
            {
                if (Directory.Exists(explorer.CurrentDirectory + frm.FolderName))
                {
                    MessageBox.Show(frm.FolderName + " already exist.\nPlease specify different name!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }
                Directory.CreateDirectory(explorer.CurrentDirectory + "\\" + frm.FolderName);
                Refresh(explorer.OtherExplorer);
                DisplayExplorer(explorer);
                SelectNewItem(explorer, explorer.CurrentDirectory + frm.FolderName);
            }
        }

        public static void NewTextDocument(UCExplorer explorer)
        {
            SaveFileDialog frm = new SaveFileDialog();
            frm.InitialDirectory = explorer.CurrentDirectory;
            frm.FileName = "NewDocument";
            frm.Filter = "Text files (*.txt)|*.txt";
            if (frm.ShowDialog().Value)
            {
                FileStream fs = File.Create(frm.FileName);
                fs.Close();
                Refresh(explorer.OtherExplorer);
                DisplayExplorer(explorer);
                SelectNewItem(explorer, frm.FileName);
            }
        }

        public static void NewWordDocument(UCExplorer explorer)
        {
            SaveFileDialog frm = new SaveFileDialog();
            frm.InitialDirectory = explorer.CurrentDirectory;
            frm.FileName = "Word Document";
            frm.Filter = "Word 2007 files (*.docx)|*.docx|Word 2003 files (*.doc)|*.doc";
            if (frm.ShowDialog().Value)
            {
                FileStream fs = File.Create(frm.FileName);
                fs.Close();
                Refresh(explorer.OtherExplorer);
                DisplayExplorer(explorer);
                SelectNewItem(explorer, frm.FileName);
            }

        }

        public static void Delete(UCExplorer explorer)
        {
            if (explorer.lvContent.SelectedItems.Count <= 0)
            {
                MessageBox.Show("No file selected!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            if (MessageBox.Show("Do you want to delete " + explorer.lvContent.SelectedItems.Count + " selected file(s)/folder(s)?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                foreach (ListViewContent item in explorer.lvContent.SelectedItems)
                {
                    if (item.Tag is DirectoryInfo)
                    {
                        Directory.Delete(item.Tag.FullName, true);
                    }
                    else
                    {
                        File.Delete(item.Tag.FullName);
                    }
                }

                Refresh(explorer.OtherExplorer);
                DisplayExplorer(explorer);
                explorer.lvContent.SelectedIndex = 0;
            }
        }

        public static void Refresh(UCExplorer explorer)
        {
            DisplayExplorer(explorer);
            explorer.lvContent.SelectedIndex = 0;
        }

        public static void SelectedAll(UCExplorer explorer)
        {
            explorer.lvContent.SelectAll();
        }

        public static void Rename(UCExplorer explorer)
        {
            if (explorer.lvContent.SelectedItems.Count <= 0)
            {
                MessageBox.Show("No file selected!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }
            if (explorer.lvContent.SelectedItems.Count > 1)
            {
                MessageBox.Show("Please choose just 1 file/folder!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }
            ListViewContent item = (ListViewContent)explorer.lvContent.SelectedItem;
            FormRename frm = new FormRename();
            frm.OriginalName = item.Tag.Name;

            if (frm.ShowDialog().Value)
            {
                if (Directory.Exists(explorer.CurrentDirectory + frm.NewName))
                {
                    MessageBox.Show(frm.NewName + " already exist.\nPlease specify different name!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }
                if (frm.NewName == item.Tag.Name)
                    return;
                Directory.Move(explorer.CurrentDirectory + item.Tag.Name, explorer.CurrentDirectory + frm.NewName);
                Refresh(explorer.OtherExplorer);
                DisplayExplorer(explorer);
                SelectNewItem(explorer, explorer.CurrentDirectory + frm.NewName);
            }


        }

        public static void Copy(UCExplorer from, UCExplorer to)
        {
            if (from.lvContent.SelectedItems.Count <= 0)
            {
                MessageBox.Show("No file selected!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            if (from.CurrentDirectory == to.CurrentDirectory)
            {
                MessageBox.Show("Source and destination path must be diffrence!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            if (MessageBox.Show("Do you want to copy " + from.lvContent.SelectedItems.Count + " selected file(s)/folder(s) \n from " + from.CurrentDirectory + "\n to " + to.CurrentDirectory + " ?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                foreach (ListViewContent item in from.lvContent.SelectedItems)
                {
                    string fileName = item.Tag.Name;
                    if (item.Tag is DirectoryInfo)
                    {
                        if (Directory.Exists(to.CurrentDirectory + fileName))
                        {
                            if (MessageBox.Show(fileName + " already exist! Overwrite?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                            {
                                FileSystem.CopyDirectory(from.CurrentDirectory + fileName, to.CurrentDirectory + fileName, true);
                            }
                        }
                        else
                        {
                            FileSystem.CopyDirectory(from.CurrentDirectory + fileName, to.CurrentDirectory + fileName, true);
                        }
                    }
                    else
                    {
                        if (File.Exists(to.CurrentDirectory + fileName))
                        {
                            if (MessageBox.Show(fileName + " already exist! Overwrite?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                            {
                                FileSystem.CopyFile(from.CurrentDirectory + fileName, to.CurrentDirectory + fileName, true);
                            }
                        }
                        else
                        {
                            FileSystem.CopyFile(from.CurrentDirectory + fileName, to.CurrentDirectory + fileName, true);
                        }
                    }
                }
                DisplayExplorer(to);
                DisplayExplorer(from);
            }
        }

        public static void Pack(UCExplorer explorer)
        {
            try
            {
                if (explorer.lvContent.SelectedItems.Count <= 0)
                {
                    MessageBox.Show("No file selected!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                if (MessageBox.Show("Do you want to archive " + explorer.lvContent.SelectedItems.Count + " selected file(s)/folder(s) ?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    SaveFileDialog frm = new SaveFileDialog();
                    frm.InitialDirectory = explorer.CurrentDirectory;
                    frm.FileName = ((ListViewContent)explorer.lvContent.SelectedItems[0]).Name;
                    frm.Filter = "Zip files (*.zip)|*.zip";
                    if (!frm.ShowDialog().Value)
                    {
                        return;
                    }
                    String password = "";
                    MessageBoxResult rs = MessageBox.Show("Do you want to use password zip?", "Question", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
                    if (rs == MessageBoxResult.Cancel)
                        return;

                    if (rs == MessageBoxResult.Yes)
                    {
                        FormCreatePassword frm2 = new FormCreatePassword();

                        if (frm2.ShowDialog().Value)
                        {
                            password = frm2.Password;
                        }
                    }

                    String zipFileName = frm.FileName;
                    String tmp = zipFileName.Substring(zipFileName.LastIndexOf('\\') + 1, zipFileName.LastIndexOf('.') - zipFileName.LastIndexOf('\\') - 1);

                    ZipFile zip = new ZipFile();

                    if (password != "")
                    {
                        zip.Password = password;
                    }
                    foreach (ListViewContent item in explorer.lvContent.SelectedItems)
                    {
                        if (item.Tag is DirectoryInfo)
                        {
                            zip.AddDirectory(item.Tag.FullName, "\\");
                        }
                        else
                        {
                            zip.AddFile(item.Tag.FullName, "\\");
                        }
                    }

                    zip.Save(zipFileName);
                    DisplayExplorer(explorer.OtherExplorer);
                    DisplayExplorer(explorer);
                    SelectNewItem(explorer, zipFileName);
                }
            }
            catch
            {
                FileHelper.ShowMessage("Can't zip!", MessageBoxImage.Error);
            }
        }

        public static void UnPack(UCExplorer explorer)
        {
            try
            {
                if (explorer.lvContent.SelectedItems.Count <= 0)
                {
                    MessageBox.Show("No file selected!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }
                if (explorer.lvContent.SelectedItems.Count > 1)
                {
                    MessageBox.Show("Please choose just 1 file/folder!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }
                ListViewContent item = (ListViewContent)explorer.lvContent.SelectedItems[0];
                if ((item.Tag.Attributes & FileAttributes.Archive) != FileAttributes.Archive)
                {
                    MessageBox.Show("Please choose a zip file!", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                if (MessageBox.Show("Do you want to unzip " + explorer.lvContent.SelectedItems.Count + " selected file(s)/folder(s) ?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    ZipFile zip = new ZipFile(item.Tag.FullName);
                    string password = null;

                    foreach (ZipEntry e in zip)
                    {
                        try
                        {
                            if (e.UsesEncryption)
                            {
                                if (password == null)
                                {
                                    FormEnterPassword frm1 = new FormEnterPassword();
                                    if (frm1.ShowDialog().Value)
                                    {
                                        password = frm1.Password;
                                    }
                                    else
                                    {
                                        FileHelper.ShowMessage("Cannot extract this entry without a password.", MessageBoxImage.Error);
                                        zip.Dispose();
                                        return;
                                    }
                                }
                                if (FileFolderExists(explorer.CurrentDirectory + e.FileName))
                                {
                                    throw new ZipException("File folder " + explorer.CurrentDirectory + e.FileName + " already exists!");
                                }
                                e.ExtractWithPassword(explorer.CurrentDirectory, ExtractExistingFileAction.OverwriteSilently, password);
                            }
                            else
                            {
                                if (FileFolderExists(explorer.CurrentDirectory + e.FileName))
                                {
                                    throw new ZipException("File folder " + explorer.CurrentDirectory + e.FileName + " already exists!");
                                }
                                e.Extract(explorer.CurrentDirectory, ExtractExistingFileAction.OverwriteSilently);
                            }
                        }
                        catch (ZipException ex)
                        {
                            FileHelper.ShowMessage(ex.Message, MessageBoxImage.Error);
                            zip.Dispose();
                            break;
                        }
                    }

                    DisplayExplorer(explorer.OtherExplorer);
                    DisplayExplorer(explorer);
                }
            }
            catch
            {
                FileHelper.ShowMessage("Can't unzip!", MessageBoxImage.Error);
            }
        }

        public static bool FileFolderExists(string path)
        {
            if (Directory.Exists(path))
            {
                return true;
            }

            if (File.Exists(path))
            {
                return true;
            }

            return false;
        }
    }
}
